package service

import (
	"buding-ai/internal/core"
	"buding-ai/internal/repository"
	"buding-ai/internal/repository/model"
	"buding-ai/internal/web/dto"
	"buding-ai/internal/web/response"
	"buding-ai/pkg/openapi"
	"buding-ai/pkg/utils/paginate"
	"context"
	"errors"
	"github.com/jinzhu/copier"
	"github.com/sashabaranov/go-openai"
	"sync"
	"time"
)

type AgentModelProviderService struct {
	agentModelProviderRepository *repository.AgentModelProviderRepository
	lock                         sync.RWMutex
}

var (
	agentModelProviderSrv  *AgentModelProviderService
	agentModelProviderOnce sync.Once
)

const providerKey = "providerKey"

type AgentModelProviderClient struct {
	Client *openai.Client
	Cfg    AgentModelProviderCfg
}
type AgentModelProviderCfg struct {
	RateLimit   int
	MaxTokens   int
	Temperature float64
	Status      int
}

func NewAgentModelProviderService() *AgentModelProviderService {
	agentModelProviderOnce.Do(func() {
		agentModelProviderSrv = &AgentModelProviderService{
			agentModelProviderRepository: repository.GetAgentModelProviderRepository(),
			lock:                         sync.RWMutex{},
		}
	})
	return agentModelProviderSrv
}

func (srv *AgentModelProviderService) Create(dto dto.AgentModelProviderDTO) error {
	exists, err := srv.agentModelProviderRepository.CheckProviderExistsByName(dto.Name)
	if err != nil {
		return errors.New("查询数据库失败" + err.Error())
	}
	if exists {
		return errors.New("提供商已存在")
	}

	// 插入数据
	var provider model.AgentModelProvider
	copier.Copy(&provider, &dto)
	// 确保新创建的记录 ID 为 0，让数据库自动分配
	provider.ID = 0
	if err := srv.agentModelProviderRepository.Create(provider); err != nil {
		return errors.New("插入失败:" + err.Error())
	}
	core.AppCache.Delete(providerKey)
	return nil
}

func (srv *AgentModelProviderService) GetById(id uint) (*response.AgentModelProviderInfoVO, error) {
	provider, err := srv.agentModelProviderRepository.GetById(id)
	if err != nil {
		return nil, err
	}
	var resp response.AgentModelProviderInfoVO
	copier.Copy(&resp, provider)
	return &resp, nil
}

func (srv *AgentModelProviderService) DeleteById(id uint) error {
	core.AppCache.Delete(providerKey)
	return srv.agentModelProviderRepository.DeleteById(id)
}

func (srv *AgentModelProviderService) Update(providerDTO dto.AgentModelProviderDTO) error {
	provider, err := srv.agentModelProviderRepository.GetById(providerDTO.ID)
	if err != nil {
		return err
	}
	if provider.ID == 0 {
		return errors.New("提供商不存在")
	}
	copier.Copy(&provider, providerDTO)
	if err := srv.agentModelProviderRepository.Update(provider); err != nil {
		return err
	}
	core.AppCache.Delete(providerKey)
	return nil
}

func (srv *AgentModelProviderService) SetDefault(id uint) error {
	// 检查提供商是否存在
	provider, err := srv.agentModelProviderRepository.GetById(id)
	if err != nil {
		return err
	}
	if provider.ID == 0 {
		return errors.New("提供商不存在")
	}
	if provider.Status != 1 {
		return errors.New("只能设置启用状态的提供商为默认")
	}
	return srv.agentModelProviderRepository.SetDefault(id)
}

func (srv *AgentModelProviderService) GetPage(request paginate.PageRequest) (*paginate.PageResponse, error) {
	pageResult, err := srv.agentModelProviderRepository.GetPage(request)
	if err != nil {
		return nil, ErrDatabaseError
	}
	return pageResult, nil
}

func (srv *AgentModelProviderService) GetDefaultProvider() (*response.AgentModelProviderInfoVO, error) {
	provider, err := srv.agentModelProviderRepository.GetDefaultProvider()
	if err != nil {
		return nil, err
	}
	var resp response.AgentModelProviderInfoVO
	copier.Copy(&resp, provider)
	return &resp, nil
}

func (srv *AgentModelProviderService) GetActiveProviders() ([]response.AgentModelProviderInfoVO, error) {
	providers, err := srv.agentModelProviderRepository.GetActiveProviders()
	if err != nil {
		return nil, err
	}
	var resp []response.AgentModelProviderInfoVO
	copier.Copy(&resp, &providers)
	return resp, nil
}

func (srv *AgentModelProviderService) GetModelList(url string, token string) ([]string, error) {
	models, err := openapi.ListModels(context.Background(), openapi.ModelProperties{
		Agent: url,
		Token: token,
	})
	if err != nil {
		return nil, err
	}
	var resp []string
	for _, model := range models {
		resp = append(resp, model.ID)
	}
	return resp, err
}

func (srv *AgentModelProviderService) GetList() ([]model.AgentModelProvider, error) {
	providers, err := srv.agentModelProviderRepository.GetActiveProviders()
	if err != nil {
		return nil, err
	}
	return providers, err
}

func (srv *AgentModelProviderService) GetClientList() (map[uint]AgentModelProviderClient, error) {
	providerCache, exist := core.AppCache.Get(providerKey)
	if exist {
		return providerCache.(map[uint]AgentModelProviderClient), nil
	}
	srv.lock.Lock()
	defer srv.lock.Unlock()
	providerCache, exist = core.AppCache.Get(providerKey)
	if exist {
		return providerCache.(map[uint]AgentModelProviderClient), nil
	}
	providers, err := srv.agentModelProviderRepository.GetActiveProviders()
	if err != nil {
		return nil, err
	}
	providerClients := make(map[uint]AgentModelProviderClient)
	for _, val := range providers {
		if val.MaxTokens == 0 {
			val.MaxTokens = 409600
		}
		providerClients[val.ID] = AgentModelProviderClient{
			Client: openapi.CreateClient(val.BaseURL, val.AuthToken),
			Cfg: AgentModelProviderCfg{
				RateLimit:   val.RateLimit,
				MaxTokens:   val.MaxTokens,
				Temperature: val.Temperature,
				Status:      val.Status,
			},
		}
	}
	core.AppCache.Set(providerKey, providerClients, time.Second*60)
	return providerClients, nil
}
